feat(plugins): register_command(override=True) to shadow a built-in command - #50054
arminanton wants to merge 2 commits into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for extending the plugin command surface. The collision is currently rejected on main (hermes_cli/plugins.py:560-569), but this implementation does not yet provide a safe, consistent override.
Problems
- CLI reaches plugin handlers only in its post-built-in fallback (
cli.py:8921-8985), and gateway does the same (gateway/run.py:10057-10072). TUI checks plugins first (tui_gateway/server.py:11892-11901), sooverride=Truewould behave differently by surface. - Current tool overrides require an explicit, fail-closed per-plugin operator opt-in (
hermes_cli/plugins.py:409-470). The new command override has no equivalent authorization boundary. - The diff has no tests or docs update, while the current collision test is at
tests/hermes_cli/test_plugins.py:1863-1872and the documented API promises built-ins take precedence atwebsite/docs/developer-guide/plugins/index.md:788-805.
Suggested changes
- Centralize authorized override resolution across CLI, gateway, and TUI; add a fail-closed per-plugin gate and cross-surface regression tests; then update the documented API and precedence contract.
Automated hermes-sweeper review.
| @@ -418,6 +418,7 @@ def register_command( | |||
| handler: Callable, | |||
| description: str = "", | |||
| args_hint: str = "", | |||
| override: bool = False, | |||
| ) -> None: | |||
| """Register a slash command (e.g. ``/lcm``) available in CLI and gateway sessions. | |||
|
|
|||
There was a problem hiding this comment.
override=True only changes registration here. CLI and gateway dispatch built-ins before their plugin fallback (cli.py:8921-8985, gateway/run.py:10057-10072), while TUI checks plugins first (tui_gateway/server.py:11892-11901). Please add a shared, authorized resolution path and cross-surface tests before exposing this option.
352b131 to
393642c
Compare
|
Rebased onto current Consistent precedence across all three surfaces (sweeper): previously CLI/gateway resolved plugins only in the post-built-in fallback while TUI checked plugins first, so Fail-closed operator opt-in (sweeper): command override is gated behind the same mechanism as tool override — a new Added a cross-surface precedence test + opt-in gate tests. |
7e72003 to
b80b40f
Compare
b80b40f to
7da8a25
Compare
7da8a25 to
5831555
Compare
Summary
Plugins can intentionally shadow a built-in slash command by passing
override=TruetoPluginContext.register_command. The default remains unchanged: a conflicting command without that flag is rejected.All three user dispatch paths consult one shared authorized override resolver before built-in handling. CLI, messaging gateway, and TUI therefore return the plugin result when an override is authorized.
Security
Third-party command overrides fail closed. A user or project plugin must receive the
commands.overridecapability throughplugins.entries.<plugin_id>.granted_capabilities, or use the deprecatedallow_command_override: truecompatibility setting. Missing consent, unreadable configuration, and ungranted plugins cannot register the override. Bundled plugins retain the existing trusted plugin treatment.Compatibility
Normal plugin commands still run through the existing fallback path. Built-in conflicts still reject by default. The legacy
allow_command_overridesetting maps to the capability registry so existing configuration can migrate without changing behavior.Tests
The plugin suite covers default conflict rejection, denied registration, capability and legacy authorization, bundled plugin authorization, and the shared resolver contract.
Behavioral dispatch tests register an authorized override of the real
/helpbuilt-in and invoke it through CLI, gateway, and TUI entry points. Each test proves that the plugin receives the raw arguments, its result reaches the caller, and built-in handling does not run. Inverse tests attempt the same registration without a grant, prove that registration fails, and then invoke/helpto confirm built-in behavior remains active.Validated with:
Result: 76 tests passed.
Result: all checks passed.